home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / CShell⁄THINK C / Utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-20  |  47.3 KB  |  1,708 lines  |  [TEXT/MPS ]

  1. /*-----------------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Collection of Utilities for DTS Sample code
  6. #
  7. #    Program:    Utilities.c.o
  8. #    File:        Utilities.c    -    C Source
  9. #
  10. #    Copyright © 1988-1990 Apple Computer, Inc.
  11. #    All rights reserved.
  12. #
  13. -----------------------------------------------------------------------------------------*/
  14.  
  15. /*-----------------------------------------------------------------------------------------
  16.     #include files
  17. -----------------------------------------------------------------------------------------*/
  18. #ifndef THINK_C
  19.  
  20. #ifndef __CONTROLS__
  21. #include <Controls.h>
  22. #endif
  23.  
  24. #ifndef __DESK__
  25. #include <Desk.h>
  26. #endif
  27.  
  28. #ifndef __EVENTS__
  29. #include <Events.h>
  30. #endif
  31.  
  32. #ifndef __FIXMATH__
  33. #include <FixMath.h>
  34. #endif
  35.  
  36. #ifndef __FONTS__
  37. #include <Fonts.h>
  38. #endif
  39.  
  40. #ifndef __MENUS__
  41. #include <Menus.h>
  42. #endif
  43.  
  44. #ifndef __OSEVENTS__
  45. #include <OSEvents.h>
  46. #endif
  47.  
  48. #ifndef __PACKAGES__
  49. #include <Packages.h>
  50. #endif
  51.  
  52. #ifndef __RESOURCES__
  53. #include <Resources.h>
  54. #endif
  55.  
  56. #ifndef __SCRIPT__
  57. #include <Script.h>
  58. #endif
  59.  
  60. #ifndef __SEGLOAD__
  61. #include <SegLoad.h>
  62. #endif
  63.  
  64. #ifndef __STRING__
  65. #include <String.h>
  66. #endif
  67.  
  68. #ifndef __SYSEQU__
  69. #include <SysEqu.h>
  70. #endif
  71.  
  72. #ifndef __TEXTEDIT__
  73. #include <TextEdit.h>
  74. #endif
  75.  
  76. #ifndef __TOOLUTILS__
  77. #include <ToolUtils.h>
  78. #endif
  79.  
  80. #ifndef __TRAPS__
  81. #include <Traps.h>
  82. #endif
  83.  
  84. #endif
  85.  
  86. #include "Utilities.h"
  87.  
  88. /*-----------------------------------------------------------------------------------------
  89.     Private Functions 
  90. -----------------------------------------------------------------------------------------*/
  91.  
  92.  
  93.  
  94. /*-----------------------------------------------------------------------------------------
  95.     Global variables -- See Utilities.h for more explanation
  96. -----------------------------------------------------------------------------------------*/
  97. short            gMachineType;            /* which machine this is */
  98. short            gSystemVersion;            /* System version number */
  99. short            gProcessorType;            /* which CPU this is */
  100. Boolean            gHasFPU;                /* true if machine has an FPU */
  101. short            gQDVersion;                /* major QD version #; 0 for original, 
  102.                                                     1 for color QD, 2 for 32-bit QD */
  103. short            gKeyboardType;            /* which type of keyboard is present */
  104. short            gAppleTalkVersion;        /* AppleTalk version number */
  105. Boolean            gHasPMMU;                /* true if machine has a PMMU or equivalent */
  106. short            gAUXVersion;            /* major A/UX version number (0 if not present) */
  107.  
  108. Boolean            gHasWaitNextEvent;
  109. short            gAppResRef;
  110. Boolean            gInBackground;
  111. Str255            gAppName;
  112. OSType            gSignature = '????';
  113. Boolean            gUtilitiesInited;
  114.  
  115.  
  116.  
  117.  
  118. /*****************************************************************************/
  119.  
  120.  
  121.  
  122. /* Given an alert ID and a window pointer the alert relates to, this function
  123. ** will center the alert’s rectangle before showing it on the proper screen.
  124. ** This follows the Apple Human Interface Guidelines for where to place a
  125. ** centered window on the screen.  If the alert is not closely associated with
  126. ** another window, pass a nil for the window pointer of the related window.  If
  127. ** you pass a nil, the alert is simply displayed where the resource
  128. ** would indicate.  Note that if an error occurs when getting the resource for
  129. ** the alert, then the alert is not displayed, and the returned value is not
  130. ** the item hit, but is the error that occured when reading the resource. */
  131.  
  132. #pragma segment UtilMain
  133. short    CenteredAlert(short alertID, WindowPtr relatedWindow)
  134. {
  135.     AlertTHndl    alertHandle;
  136.     WindowPtr    tempWindow;
  137.     Rect        alertRect;
  138.     short        itemHit;
  139.     char        hstate;
  140.     OSErr        err;
  141.     
  142.     alertHandle = (AlertTHndl)GetAppResource('ALRT', alertID, &err);
  143.     if (err) return((short)err);
  144.  
  145.     hstate = LockHandleHigh((Handle)alertHandle);
  146.         /* Do our part to help prevent fragmentation. */
  147.  
  148.     alertRect = (*alertHandle)->boundsRect;
  149.         /* Preserve the real alert bounding rectangle. */
  150.  
  151.     if (tempWindow = NewWindow(nil, &alertRect, '', false, dBoxProc,
  152.                               (WindowPtr)nil, false, 0)) {
  153.         /* Use an invisible temporary window to calculate where the alert will go. */
  154.  
  155.         (*alertHandle)->boundsRect = CenterWindow(tempWindow, relatedWindow);
  156.         DisposeWindow(tempWindow);
  157.     }
  158.  
  159. #ifndef THINK_C
  160.     itemHit = Alert(alertID, (ModalFilterProcPtr)nil);
  161. #else
  162.     itemHit = Alert(alertID, nil);
  163. #endif
  164.  
  165.     (*alertHandle)->boundsRect = alertRect;
  166.         /* Restore the resource's bounding rect, so if this resource is ever used
  167.         ** not through this function, it will open where the resource indicates. */
  168.  
  169.     HSetState((Handle)alertHandle, hstate);
  170.     return(itemHit);
  171. }
  172.  
  173.  
  174.  
  175. /*****************************************************************************/
  176.  
  177.  
  178.  
  179. /* Given two rects, this function centers the second one within the first. */
  180.  
  181. #pragma segment UtilMain
  182. void    CenterRectInRect(Rect outerRect, Rect *innerRect)
  183. {
  184.     PositionRectInRect(outerRect, innerRect, FixRatio(1, 2), FixRatio(1, 2));
  185. }
  186.  
  187.  
  188.  
  189. /*****************************************************************************/
  190.  
  191.  
  192.  
  193. /* Center a window within a particular device.  The device to center the window
  194. ** within is determined by passing a related window.  This allows related
  195. ** windows to be kept on the same device.  This is useful if an alert related
  196. ** to a specific window, for example. */
  197.  
  198. #pragma segment UtilMain
  199. Rect    CenterWindow(WindowPtr window, WindowPtr relatedWindow)
  200. {
  201.     WindowPtr    whichDevice;
  202.     Rect        deviceRect, oldWindowRect, newWindowRect, contentRect;
  203.  
  204.     if (!(whichDevice = relatedWindow)) whichDevice = window;
  205.         /* If we have a window to center against, use the device for that window,
  206.         ** else use the device for the window that is getting centered. */
  207.  
  208.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  209.         /* We now have the rectangle of the device we want to center within. */
  210.  
  211.     oldWindowRect = newWindowRect = GetWindowStructureRect(window);
  212.  
  213.     PositionRectInRect(deviceRect, &newWindowRect, FixRatio (1, 2),
  214.                        FixRatio (1, 3));
  215.         /* Figure out the new window strucRect so we can compare it against
  216.         ** the old strucRect.  This will tell us how much to move the window. */
  217.  
  218.     contentRect = GetWindowContentRect(window);
  219.         /* Get where the window is now. */
  220.  
  221.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  222.                             newWindowRect.top  - oldWindowRect.top);
  223.         /* Calculate the new content rect. */
  224.  
  225.     MoveWindow(window, contentRect.left, contentRect.top, false);
  226.         /* Move the window to the new location. */
  227.  
  228.     return(contentRect);
  229. }
  230.  
  231.  
  232.  
  233. /*****************************************************************************/
  234.  
  235.  
  236.  
  237. /* Close a window.  This handles desk accessory and application windows.  Use
  238. ** this call (instead of DisposeAnyWindow) if the memory for the window was
  239. ** allocated by you.  (Same as CloseWindow v.s. DisposeWindow.) */
  240.  
  241. #pragma segment UtilMain
  242. void    CloseAnyWindow(WindowPtr window)
  243. {
  244.     if (IsDAWindow(window))
  245.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  246.     else {
  247.         if (IsAppWindow(window))
  248.             CloseWindow(window);
  249.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  250.             CloseDialog((DialogPtr)window);
  251.     }
  252. }
  253.  
  254.  
  255.  
  256. /*****************************************************************************/
  257.  
  258.  
  259.  
  260. /* Dispose a window.  This handles desk accessory and application windows.  Use
  261. ** this call (instead of CloseAnyWindow) if you want the memory for the window
  262. ** record to be disposed of.  (Same as CloseWindow v.s. DisposeWindow.) */
  263.  
  264. #pragma segment UtilMain
  265. void    DisposeAnyWindow(WindowPtr window)
  266. {
  267.     if (IsDAWindow(window))
  268.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  269.     else {
  270.         if (IsAppWindow(window))
  271.             DisposeWindow(window);
  272.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  273.             DisposDialog((DialogPtr)window);
  274.     }
  275. }
  276.  
  277.  
  278.  
  279. /*****************************************************************************/
  280.  
  281.  
  282.  
  283. /* Display an alert that tells the user an error occurred, then exit the
  284. ** program.  This function is used as an ultimate bail-out for serious errors
  285. ** that prohibit the continuation of the application.  Errors that do not
  286. ** require the termination of the application should be handled in a different
  287. ** manner. */  
  288.  
  289. #pragma segment UtilMain
  290. void    DeathAlert(short errResID, short errStringIndex)
  291. {
  292.     ErrorAlert(errResID, errStringIndex);
  293.     ExitToShell();
  294. }
  295.  
  296.  
  297.  
  298. /*****************************************************************************/
  299.  
  300.  
  301.  
  302. /* Display an alert that tells the user an error occurred, then exit the
  303. ** program.  This function is used as an ultimate bail-out for serious errors
  304. ** that prohibit the continuation of the application.  Errors that do not
  305. ** require the termination of the application should be handled in a different
  306. ** manner.  The message parameter is an error code that is to be displayed. */
  307.  
  308. #pragma segment UtilMain
  309. void    DeathAlertMessage(short errResID, short errStringIndex, short message)
  310. {
  311.     ErrorAlertMessage(errResID, errStringIndex, message);
  312.     ExitToShell();
  313. }
  314.  
  315.  
  316.  
  317. /*****************************************************************************/
  318.  
  319.  
  320.  
  321. /* Display an alert that tells the user an error occurred. */
  322.  
  323. #pragma segment UtilMain
  324. void    ErrorAlert(short errResID, short errStringIndex)
  325. {
  326.     ErrorAlertMessage(errResID, errStringIndex, 0);
  327. }
  328.  
  329.  
  330.  
  331. /*****************************************************************************/
  332.  
  333.  
  334.  
  335. /* Display an alert to inform the user of an error.  errStringIndex acts as an
  336. ** index into a STR# resource of error messages.  If no errStringIndex is
  337. ** given, i.e. = 0, then use a standard message.  If message is not noErr then
  338. ** display it as well.
  339. **
  340. ** BUG NOTE:  GetIndString returns a bogus String if the index is
  341. **            not positive. */
  342.   
  343. #pragma segment UtilMain
  344. void    ErrorAlertMessage(short errResID, short errStringIndex, short message)
  345. {
  346.     Str255    msg1, msg2;
  347.  
  348.     SetCursor(&QD(arrow));
  349.  
  350.     if (errStringIndex <= 0) {
  351.         errStringIndex = eStandardErr;
  352.         errResID = rUtilStrings;
  353.     }
  354.     GetIndString(msg1, errResID, errStringIndex);
  355.  
  356.     if (message == noErr) {
  357.         ParamText(msg1, '', '', '');
  358.         CenteredAlert(rUtilErrorAlert, nil);
  359.     } else {
  360.         NumToString(message, (StringPtr)&msg2);
  361.         ParamText(msg1, msg2, '', '');
  362.         CenteredAlert(rUtilErrorMessageAlert, nil);
  363.     }
  364. }
  365.  
  366.  
  367.  
  368. /*****************************************************************************/
  369.  
  370.  
  371.  
  372. /* FindSysFolder returns the (real) vRefNum, and the DirID of the current
  373. ** system folder.  It uses the Folder Manager if present, otherwise it falls
  374. ** back to SysEnvirons.  It returns zero on success, otherwise a standard
  375. ** system error. */
  376.  
  377. #pragma segment UtilMain
  378. OSErr    FindSysFolder(short *foundVRefNum, long *foundDirID)
  379. {
  380.     long            gesResponse;
  381.     SysEnvRec        envRec;
  382.     WDPBRec            myWDPB;
  383.     unsigned char    volName[34];
  384.     OSErr            err;
  385.     
  386.     
  387.     *foundVRefNum = 0;
  388.     *foundDirID = 0;
  389.     if (!Gestalt (gestaltFindFolderAttr, &gesResponse) &&
  390.         BTstQ (gesResponse, gestaltFindFolderPresent)) {    /* Does Folder Manager exist? */
  391.             err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder, 
  392.                 foundVRefNum, foundDirID);
  393.     } else {
  394.         /* Gestalt can't give us the answer, so we resort to SysEnvirons */
  395.         if (!(err = SysEnvirons (curSysEnvVers, &envRec))) {
  396.             myWDPB.ioVRefNum = envRec.sysVRefNum;
  397.             volName[0] = '\000';                    /* Zero volume name */
  398.             myWDPB.ioNamePtr = volName;
  399.             myWDPB.ioWDIndex = 0;
  400.             myWDPB.ioWDProcID = 0;
  401.             if (!(err = PBGetWDInfo (&myWDPB, 0))) {
  402.                 *foundVRefNum = myWDPB.ioWDVRefNum;
  403.                 *foundDirID = myWDPB.ioWDDirID;
  404.             }
  405.         }
  406.     }
  407.     return (err);
  408. }
  409.  
  410.  
  411.  
  412. /*****************************************************************************/
  413.  
  414.  
  415.  
  416. /* GetAppIndResource gets a resource from the application's resource file
  417. ** by index. */
  418.  
  419. #pragma segment UtilMain
  420. Handle    GetAppIndResource(ResType theType, short index, OSErr *err)
  421. {
  422. #pragma unused (err)
  423.  
  424.     short    savedResFile;
  425.     Handle    returnHandle;
  426.     
  427.     savedResFile = CurResFile ();
  428.     UseResFile (gAppResRef);
  429.     returnHandle = Get1IndResource(theType, index);
  430.     UseResFile (savedResFile);
  431.     return (returnHandle);
  432. }
  433.  
  434.  
  435.  
  436. /*****************************************************************************/
  437.  
  438.  
  439.  
  440. /* GetAppNamedResource gets a resource from the application's resource file
  441. ** by name. */
  442.  
  443. #pragma segment UtilMain
  444. Handle    GetAppNamedResource(ResType theType, Str255 name, OSErr *err)
  445. {
  446.     short    savedResFile;
  447.     Handle    returnHandle;
  448.     
  449.     savedResFile = CurResFile ();
  450.     UseResFile (gAppResRef);
  451.     returnHandle = Get1NamedResource(theType, name);
  452.     *err = ResError();
  453.     UseResFile (savedResFile);
  454.     return (returnHandle);
  455. }
  456.  
  457.  
  458.  
  459. /*****************************************************************************/
  460.  
  461.  
  462.  
  463. /* GetAppResource gets a resource from the application's resource file by
  464. ** resource ID. */
  465.  
  466. #pragma segment UtilMain
  467. Handle    GetAppResource(ResType theType,short theID, OSErr *err)
  468. {
  469.     short    savedResFile;
  470.     Handle    returnHandle;
  471.     
  472.     savedResFile = CurResFile ();
  473.     UseResFile (gAppResRef);
  474.     returnHandle = Get1Resource(theType, theID);
  475.     *err = ResError();
  476.     UseResFile (savedResFile);
  477.     return (returnHandle);
  478. }
  479.  
  480.  
  481.  
  482. /*****************************************************************************/
  483.  
  484.  
  485.  
  486. /* Checks for the presence of A/UX by whatever means is appropriate.  Returns
  487. ** the major version number of A/UX (i.e. 0 if A/UX is not present, 1 for
  488. ** any 1.x.x version 2 for any 2.x version, etc.
  489. **
  490. ** This code should work for all past, present and future A/UX systems. */
  491.  
  492. #define HWCfgFlags    0xB22    /* Low memory global used to check if A/UX is running */
  493.  
  494. #pragma segment UtilMain
  495. short    GetAUXVersion(void)
  496. {
  497.     long    auxVersion;
  498.     short    err;
  499.     short    *flagPtr;
  500.     
  501.         /*
  502.      *    This code assumes the Gestalt glue checks for the presence of the _Gestalt
  503.      *    trap and does something intelligent if the trap is unavailable, i.e.
  504.      *    return unknown selector.
  505.      */
  506.     auxVersion = 0;
  507.     err = Gestalt(gestaltAUXVersion, &auxVersion);
  508.     /*
  509.      *    If gestaltUnknownErr or gestaltUndefSelectorErr was returned, then either 
  510.      *    we weren't running on A/UX, or the _Gestalt trap is unavailable so use 
  511.      *    HWCfgFlags instead.
  512.      *    All other errors are ignored (implies A/UX not present).
  513.      */
  514.     if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {    /* Use HWCfgFlags */
  515.         flagPtr = (short *) HWCfgFlags;
  516.         if (BTstQ(*flagPtr, 9))
  517.             auxVersion = 0x100;            /* Do Have A/UX, so assume version 1.x.x */
  518.     }
  519.     /*
  520.      *    Now right shift auxVersion by 8 bits to get major version number
  521.      */
  522.     auxVersion >>= 8;
  523.     return((short)auxVersion);
  524. }
  525.  
  526.  
  527.  
  528. /*****************************************************************************/
  529.  
  530.  
  531.  
  532. /* Given a dialog ID and a window pointer the dialog relates to, this function
  533. ** will center the dialog’s rectangle before showing it on the proper screen.
  534. ** This follows the Apple Human Interface Guidelines for where to place a
  535. ** centered window on the screen.  If the dialog is not closely associated with
  536. ** another window, pass a nil for the window pointer of the related window.  If
  537. ** you pass a nil, the dialog is simply displayed where the resource
  538. ** would indicate. */
  539.  
  540. #pragma segment UtilMain
  541. DialogPtr    GetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind)
  542. {
  543.     DialogTHndl        dlogResource;
  544.     DialogPtr        dialog;
  545.     Boolean            oldVis;
  546.     char            hstate;
  547.     OSErr            err;
  548.     
  549.     dialog = nil;
  550.     if (dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err)) {
  551.         hstate = LockHandleHigh((Handle)dlogResource);
  552.         oldVis = (*dlogResource)->visible;
  553.         (*dlogResource)->visible = false;
  554.         if (dialog = GetNewDialog(id, storage, behind)) {
  555.             CenterWindow(dialog, relatedWindow);
  556.             if (oldVis) ShowWindow(dialog);
  557.         }
  558.         (*dlogResource)->visible = oldVis;
  559.         HSetState((Handle)dlogResource, hstate);
  560.     }
  561.     return(dialog);
  562. }
  563.  
  564.  
  565.  
  566. /*****************************************************************************/
  567.  
  568.  
  569.  
  570. /* Given a window ID and a window pointer the window relates to, this function
  571. ** will center the window’s rectangle before showing it on the proper screen.
  572. ** This follows the Apple Human Interface Guidelines for where to place a
  573. ** centered window on the screen.  If the window is not closely associated with
  574. ** another window, pass a nil for the window pointer of the related window.  If
  575. ** you pass a nil, the window is simply displayed where the resource
  576. ** would indicate. */
  577.  
  578. #pragma segment UtilMain
  579. WindowPtr    GetCenteredWindow(short id, Ptr storage, WindowPtr relatedWindow,
  580.                               WindowPtr behind, Boolean inColor)
  581. {
  582.     return(GetSomeKindOfWindow(CenterWindow, id, storage, relatedWindow, behind, inColor));
  583. }
  584.  
  585.  
  586.  
  587. /*****************************************************************************/
  588.  
  589.  
  590.  
  591. #pragma segment UtilMain
  592. Boolean GetCheckOrRadio(DialogPtr dlgPtr, short itemNo)
  593. {
  594.     short    iKind;
  595.     Handle    iHandle;
  596.     Rect    iRect;
  597.  
  598.     GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  599.     return(GetCtlValue((ControlHandle)iHandle) != 0);
  600. }
  601.  
  602.  
  603.  
  604. /*****************************************************************************/
  605.  
  606.  
  607.  
  608. /* GetGestaltResult returns the result value from Gestalt for the specified
  609. ** selector.  If Gestalt returned an error GetGestaltResult returns zero.
  610. ** Use of this function is only cool if we don't care whether Gestalt returned
  611. ** an error.  In many cases you may need to know the exact Gestalt error code
  612. ** so then this function would be inappropriate.
  613. ** See GetAUXVersion for an example. */
  614.  
  615. #pragma segment UtilMain
  616. long    GetGestaltResult(OSType gestaltSelector)
  617. {
  618.     long    gestaltResult;
  619.     
  620.     if (Gestalt(gestaltSelector, &gestaltResult) == noErr)
  621.         return(gestaltResult);
  622.     else
  623.         return(0);
  624. }
  625.  
  626.  
  627.  
  628. /*****************************************************************************/
  629.  
  630.  
  631.  
  632. /* Get the global coordinates of the mouse.  When you call OSEventAvail it will
  633. ** return either a pending event or a null event.  In either case, the where
  634. ** field of the event record will contain the current position of the mouse in
  635. ** global coordinates and the modifiers field will reflect the current state of
  636. ** the modifiers.  Another way to get the global coordinates is to call
  637. ** GetMouse and LocalToGlobal, but that requires being sure that thePort is set
  638. ** to a valid port. */
  639.  
  640. #pragma segment UtilMain
  641. Point    GetGlobalMouse(void)
  642. {
  643.     EventRecord    event;
  644.     
  645.     OSEventAvail(kNoEvents, &event);    /* we aren’t interested in any events */
  646.     return(event.where);                /* just the mouse position */
  647. }
  648.  
  649.  
  650.  
  651. /*****************************************************************************/
  652.  
  653.  
  654.  
  655. /* Given a window, this will return the top left point of the window’s port in
  656. ** global coordinates.  Something this doesn’t include is the window’s drag
  657. ** region (or title bar).  This returns the top left point of the window’s
  658. ** content area only. */
  659.   
  660. #pragma segment UtilMain
  661. Point    GetGlobalTopLeft(WindowPtr window)
  662. {
  663.     GrafPtr            oldPort;
  664.     Point            globalPt;
  665.     
  666.     GetPort(&oldPort);
  667.     SetPort(window);
  668.     globalPt = TopLeft(window->portRect);
  669.     LocalToGlobal(&globalPt);
  670.     SetPort(oldPort);
  671.     return(globalPt);
  672. }
  673.  
  674.  
  675.  
  676. /*****************************************************************************/
  677.  
  678.  
  679.  
  680. /* Return the amount of free space on the volume in KBytes. -1 is returned as
  681. ** the size if there is an error. */
  682.  
  683. #pragma segment UtilInit
  684. long    GetKFreeSpace(short vRefNum)
  685. {
  686.     HParamBlockRec    pb;
  687.     OSErr            err;
  688.  
  689.     pb.volumeParam.ioNamePtr = nil;            /* we don't care about the name */
  690.     pb.volumeParam.ioVRefNum = vRefNum;
  691.     pb.volumeParam.ioVolIndex = 0;            /* use ioVRefNum only */
  692.     err = PBHGetVInfo(&pb, false);
  693.  
  694.     if (err == noErr)
  695.         return((pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz) / 1024);
  696.     else
  697.         return(-1);
  698. }
  699.  
  700.  
  701.  
  702. /*****************************************************************************/
  703.  
  704.  
  705.  
  706. #pragma segment UtilMain
  707. Rect    GetMainScreenRect(void)
  708. {
  709.     GDHandle    mainDevice;
  710.     GrafPtr        mainPort;
  711.  
  712.     if (gQDVersion > kQDOriginal) {
  713.         mainDevice = GetMainDevice();
  714.         return((*mainDevice)->gdRect);
  715.     } else {
  716.         GetWMgrPort(&mainPort);
  717.         return(mainPort->portRect);
  718.     }
  719. }
  720.  
  721.  
  722.  
  723. /*****************************************************************************/
  724.  
  725.  
  726.  
  727. /* Find the greatest overlap device for the given global rectangle. */
  728.  
  729. #pragma segment UtilInit
  730. GDHandle    GetRectDevice(Rect globalRect)
  731. {
  732.     long        area;
  733.     long        maxArea;
  734.     GDHandle    device;
  735.     GDHandle    deviceToReturn;
  736.     Rect        intersection;
  737.  
  738.     deviceToReturn = GetMainDevice();            /* Use as default choice. */
  739.     maxArea = 0;
  740.  
  741.     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  742.         if (TestDeviceAttribute(device, screenDevice)
  743.           && TestDeviceAttribute(device, screenActive)
  744.           && SectRect(&globalRect, &((*device)->gdRect), &intersection)) {
  745.             area = (intersection.right - intersection.left) *
  746.                    (intersection.bottom - intersection.top);
  747.             if (area > maxArea) {
  748.                 deviceToReturn = device;
  749.                 maxArea = area;
  750.             }
  751.         }
  752.     }
  753.     return(deviceToReturn);
  754. }
  755.  
  756.  
  757.  
  758. /*****************************************************************************/
  759.  
  760.  
  761.  
  762. /* Find the rect of the greatest overlap device for the given global rect. */
  763.  
  764. #pragma segment UtilInit
  765. Rect    GetRectDeviceRect(Rect globalRect)
  766. {
  767.     if (gQDVersion > kQDOriginal)
  768.         return((*GetRectDevice(globalRect))->gdRect);
  769.     else
  770.         return(GetMainScreenRect());
  771. }
  772.  
  773.  
  774.  
  775. /*****************************************************************************/
  776.  
  777.  
  778.  
  779. /* Given a window positioning procedure pointer, a window ID and a window
  780. ** pointer the window relates to, this function open a new window by either
  781. ** a NewCWindow or a NewWindow call, depending on the value of inColor.  The
  782. ** window will be opened invisible, independent of what the resource says.
  783. ** Once the window is opened successfully, the positioning procedure is
  784. ** called.  The positioning procedure is passed a pointer to the just-opened
  785. ** invisible window and a pointer to the related window.  It is up to the
  786. ** positioning procedure to move the invisible window to the correct location
  787. ** on the correct device.  Once the positioning procedure returns, the window
  788. ** will be made visible if so indicated by the resource. */
  789.  
  790. #pragma segment UtilMain
  791. WindowPtr    GetSomeKindOfWindow(PositionWndProcPtr whatKind, short windID,
  792.                                 Ptr storage, WindowPtr relatedWindow,
  793.                                 WindowPtr behind, Boolean inColor)
  794. {
  795.     WindowTHndl        windowResource;
  796.     WindowTemplate    wt;                /* Window template. */
  797.     WindowPtr        aWindow;
  798.     OSErr            err;
  799.  
  800.     if (!gQDVersion) inColor = false;
  801.  
  802.     aWindow = nil;        /* Assume we will fail.  (Good attitude.) */
  803.  
  804.     if (!storage) storage = NewPtr(sizeof(WindowRecord));
  805.  
  806.     if (storage) {            /* If we have memory for the window record... */
  807.  
  808.         if (windowResource = (WindowTHndl)GetAppResource('WIND', windID, &err)) {
  809.             /* If we can load the window resource... */
  810.  
  811.             wt = **windowResource;        /* Make local copy of resource. */
  812.  
  813.             aWindow = (inColor ? NewCWindow(storage, &wt.boundsRect,
  814.                                             wt.title, false, wt.procID,
  815.                                             behind, wt.goAwayFlag, wt.refCon)
  816.                                : NewWindow(storage, &wt.boundsRect, wt.title,
  817.                                            false, wt.procID,
  818.                                            behind, wt.goAwayFlag, wt.refCon));
  819.                 /* Open either a regular or color window. */
  820.  
  821.             if (aWindow) {        /* If we were able to open a window... */
  822.                 (*whatKind)(aWindow, relatedWindow);
  823.                     /* Call the designated window positioning procedure. */
  824.  
  825.                 if (wt.visible) ShowWindow(aWindow);
  826.                     /* If resource says window should be visible, do it. */
  827.             }
  828.         }
  829.         if (!aWindow) DisposPtr(storage);
  830.             /* If we failed, then get rid of window record memory. */
  831.     }
  832.  
  833.     return(aWindow);
  834. }
  835.  
  836.  
  837.  
  838. /*****************************************************************************/
  839.  
  840.  
  841.  
  842. /* Given a window ID and a window pointer the window relates to, this function
  843. ** will stagger the window’s rectangle before showing it on the proper screen.
  844. ** This follows the Apple Human Interface Guidelines for where to place a
  845. ** staggered window on the screen.  If the window is not closely associated
  846. ** with another window, pass a nil for the window pointer of the related
  847. ** window.  If you pass a nil, the window is simply displayed where the
  848. ** resource would indicate. */
  849.  
  850. #pragma segment UtilMain
  851. WindowPtr    GetStaggeredWindow(short id, Ptr storage, WindowPtr relatedWindow,
  852.                                WindowPtr behind, Boolean inColor)
  853. {
  854.     return(GetSomeKindOfWindow(StaggerWindow, id, storage, relatedWindow, behind, inColor));
  855. }
  856.  
  857.  
  858.  
  859. /*****************************************************************************/
  860.  
  861.  
  862.  
  863. /*    Check the bits of a trap number to determine its type. */
  864.  
  865. #pragma segment UtilInit
  866. TrapType    GetTrapType(short theTrap)
  867. {
  868.     /* OS traps start with A0, Tool with A8 or AA. */
  869.     if ((theTrap & 0x0800) == 0)                    /* per D.A. */
  870.         return (OSTrap);
  871.     else
  872.         return (ToolTrap);
  873. }
  874.  
  875.  
  876.  
  877. /*****************************************************************************/
  878.  
  879.  
  880.  
  881. /* Given a window pointer, return the global rectangle that encloses the
  882. ** content area of the window. */
  883.  
  884. #pragma segment UtilMain
  885. Rect    GetWindowContentRect(WindowPtr window)
  886. {
  887.     WindowPtr    oldPort;
  888.     Rect        contentRect;
  889.  
  890.     GetPort(&oldPort);
  891.     SetPort(window);
  892.     contentRect = window->portRect;
  893.     LocalToGlobalRect(&contentRect);
  894.     SetPort(oldPort);
  895.     return(contentRect);
  896. }
  897.  
  898.  
  899.  
  900. /*****************************************************************************/
  901.  
  902.  
  903.  
  904. /* This procedure counts the number of windows in the application plane.
  905. ** You have the choices of also including DAs and invisible windows in
  906. ** this count. */
  907.  
  908. #pragma segment UtilMain
  909. short    GetWindowCount(Boolean includeDAs, Boolean includeInvisibles)
  910. {
  911.     WindowPeek    window;
  912.     short        count;
  913.  
  914.     for (count = 0, window = *(WindowPeek *)WindowList;
  915.          (window != nil); window = window->nextWindow) {
  916.  
  917.         if ((window->windowKind < 0) && (!includeDAs)) continue;
  918.         if ((window->visible) || (includeInvisibles)) count++;
  919.     }
  920.     return (count);
  921. }
  922.  
  923.  
  924.  
  925. /*****************************************************************************/
  926.  
  927.  
  928.  
  929. /* Find the greatest overlap device for the given window. */
  930.  
  931. #pragma segment UtilInit
  932. GDHandle    GetWindowDevice(WindowPtr window)
  933. {
  934.     return(GetRectDevice(GetWindowStructureRect(window)));
  935. }
  936.  
  937.  
  938.  
  939. /*****************************************************************************/
  940.  
  941.  
  942.  
  943. /* Given a window pointer, find the device that contains most of the window
  944. ** and return the device's bounding rectangle. */
  945.  
  946. #pragma segment UtilMain
  947. Rect    GetWindowDeviceRect(WindowPtr window)
  948. {
  949.     if (gQDVersion > kQDOriginal)
  950.         return((*GetWindowDevice(window))->gdRect);
  951.     else
  952.         return(GetMainScreenRect());
  953. }
  954.  
  955.  
  956.  
  957. /*****************************************************************************/
  958.  
  959.  
  960.  
  961. /* Given a window pointer, find the device that contains most of the window
  962. ** and return the device's bounding rectangle.  If this device is the main
  963. ** device, then remove the menubar area from the rectangle. */
  964.  
  965. #pragma segment UtilMain
  966. Rect    GetWindowDeviceRectNMB(WindowPtr window)
  967. {
  968.     Rect        deviceRect, tempRect;
  969.  
  970.     deviceRect = GetWindowDeviceRect(window);
  971.     tempRect = GetMainScreenRect();
  972.     if (EqualRect(&deviceRect, &tempRect)) deviceRect.top += GetMBarHeight();
  973.  
  974.     return(deviceRect);
  975. }
  976.  
  977.  
  978.  
  979. /*****************************************************************************/
  980.  
  981.  
  982.  
  983. /* This procedure is used to get the rectangle that surrounds the entire
  984. ** structure of a window.  This is true whether or not the window is visible.
  985. ** If the window is visible, then it is a simple matter of using the bounding
  986. ** rectangle of the structure region.  If the window is invisible, then the
  987. ** strucRgn is not correct.  To make it correct, then window has to be moved
  988. ** way off the screen and then made visible.  This generates a valid strucRgn,
  989. ** although it is valid for the position that is way off the screen.  It still
  990. ** needs to be offset back into the original position.  Once the bounding
  991. ** rectangle for the strucRgn is obtained, the window can then be hidden again
  992. ** and moved back to its correct location.  Note that ShowHide is used,
  993. ** instead of ShowWindow and HideWindow.  HideWindow can change the plane of
  994. ** the window.  Also, ShowHide does not affect the hiliting of windows. */
  995.  
  996. #pragma segment UtilMain
  997. Rect    GetWindowStructureRect(WindowPtr window)
  998. {
  999. #define kOffscreenLoc 0x4000
  1000.  
  1001.     GrafPtr        oldPort;
  1002.     Rect        structureRect;
  1003.     Point        windowLoc;
  1004.     
  1005.     if (((WindowPeek)window)->visible)
  1006.         structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1007.  
  1008.     else {
  1009.         GetPort(&oldPort);
  1010.         SetPort(window);
  1011.         windowLoc = GetGlobalTopLeft(window);
  1012.         MoveWindow(window, windowLoc.h, kOffscreenLoc, false);
  1013.         ShowHide(window, true);
  1014.         structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1015.         ShowHide(window, false);
  1016.         MoveWindow(window, windowLoc.h, windowLoc.v, false);
  1017.         SetPort(oldPort);
  1018.         OffsetRect(&structureRect, 0, windowLoc.v - kOffscreenLoc);
  1019.     }
  1020.     return(structureRect);
  1021. }
  1022.  
  1023.  
  1024.  
  1025. /*****************************************************************************/
  1026.  
  1027.  
  1028.  
  1029. #pragma segment UtilMain
  1030. void    GlobalToLocalRect(Rect *aRect)
  1031. {
  1032.     GlobalToLocal(&TopLeft(*aRect));
  1033.     GlobalToLocal(&BotRight(*aRect));
  1034. }
  1035.  
  1036.  
  1037.  
  1038. /*****************************************************************************/
  1039.  
  1040.  
  1041.  
  1042. #pragma segment UtilInit
  1043. void    InitToolBox(void)
  1044. {
  1045.     InitGraf((Ptr) &QD(thePort));
  1046.     InitFonts();
  1047.     InitWindows();
  1048.     InitMenus();
  1049.     TEInit();
  1050.     InitDialogs(nil);
  1051.     InitCursor();
  1052. }
  1053.     
  1054.  
  1055.  
  1056. /*****************************************************************************/
  1057.  
  1058.  
  1059.  
  1060. /* InitUtilities sets up some global variables for use by the utilities
  1061. ** package.  If you call StandardInitialization, you don't need to call this,
  1062. ** as it will do it for you. */ 
  1063.  
  1064. #pragma segment UtilInit
  1065. void    InitUtilities(void)
  1066. {
  1067.     Handle    apParam;
  1068.     Handle    bndlResource;
  1069.     OSErr    err;
  1070.  
  1071.     gUtilitiesInited = false;
  1072.  
  1073.     /* Init all the Gestalt variables */
  1074.     gMachineType = GetGestaltResult (gestaltMachineType);
  1075.     gSystemVersion = GetGestaltResult (gestaltSystemVersion);
  1076.     gProcessorType = GetGestaltResult (gestaltProcessorType);
  1077.  
  1078.     /* We only concern ourselves with there being an FPU, not which type it is */
  1079.     gHasFPU = (GetGestaltResult (gestaltFPUType) != gestaltNoFPU);
  1080.     
  1081.     /*
  1082.      *    We only concern ourselves with the major QD version number
  1083.      *    0 for original QD, 1 for 8-bit color QD, and 2 for 32-bit QD
  1084.      */
  1085.     gQDVersion = (GetGestaltResult (gestaltQuickdrawVersion) >> 8) & 0xFF;
  1086.     gKeyboardType = GetGestaltResult (gestaltKeyboardType);
  1087.     gAppleTalkVersion = GetGestaltResult (gestaltAppleTalkVersion);
  1088.     
  1089.     /* We only concern ourselves with there being an PMMU, not which type it is */
  1090.     gHasPMMU = GetGestaltResult (gestaltMMUType) >= gestalt68851;
  1091.     gAUXVersion = GetAUXVersion ();
  1092.  
  1093.     gHasWaitNextEvent = TrapExists(_WaitNextEvent);
  1094.     gInBackground = false;
  1095.     
  1096. /* 
  1097. 10/16/90 pvh/MacDTS
  1098. With GetAppParams(), THINK C in project mode returns the project resource file AND NOT 
  1099. the .rsrc file, which is what one really wants (trust me).  If THINK is present we will 
  1100. return CurResFile() which will be the .rsrc file instead.  The name will still be the 
  1101. project name in project mode, so be aware of that.
  1102. */
  1103.     GetAppParms(gAppName, &gAppResRef, &apParam);
  1104. #ifdef THINK_C
  1105.     gAppResRef = CurResFile();            /* returns refNum of .rsrc file */
  1106. #endif
  1107.  
  1108.     bndlResource = GetAppIndResource('BNDL', 1, &err);
  1109.     if (bndlResource)
  1110.         gSignature = *(OSType *) (*bndlResource);
  1111.  
  1112.     gUtilitiesInited = true;
  1113. }
  1114.  
  1115.  
  1116.  
  1117. /*****************************************************************************/
  1118.  
  1119.  
  1120.  
  1121. /* Check to see if a window belongs to the application.  If the window pointer
  1122. ** passed was nil, then it could not be an application window.  WindowKinds
  1123. ** that are negative belong to the system and windowKinds less than userKind
  1124. ** are reserved by Apple except for windowKinds equal to dialogKind, which
  1125. ** mean it is a dialog. */  
  1126.  
  1127. #pragma segment UtilMain
  1128. Boolean    IsAppWindow(WindowPtr window)
  1129. {
  1130.     if (window)
  1131.         return (((WindowPeek)window)->windowKind >= userKind);
  1132.     else 
  1133.         return false;
  1134.  
  1135. }
  1136.  
  1137.  
  1138.  
  1139. /*****************************************************************************/
  1140.  
  1141.  
  1142.  
  1143. /* Check to see if a window belongs to a desk accessory. */
  1144.  
  1145. #pragma segment UtilMain
  1146. Boolean    IsDAWindow(WindowPtr window)
  1147. {
  1148.     if (window)    /* DA windows have negative windowKinds */
  1149.         return (((WindowPeek) window)->windowKind < 0);
  1150.     else
  1151.         return false;
  1152. }
  1153.  
  1154.  
  1155.  
  1156. /*****************************************************************************/
  1157.  
  1158.  
  1159.  
  1160. #pragma segment UtilMain
  1161. void    LocalToGlobalRect(Rect *aRect)
  1162. {
  1163.     LocalToGlobal(&TopLeft(*aRect));
  1164.     LocalToGlobal(&BotRight(*aRect));
  1165. }
  1166.  
  1167.  
  1168.  
  1169. /*****************************************************************************/
  1170.  
  1171.  
  1172.  
  1173. #pragma segment UtilMain
  1174. char    LockHandleHigh(Handle theHandle)
  1175. {
  1176.     char    hstate;
  1177.  
  1178.     hstate = HGetState(theHandle);
  1179.     MoveHHi(theHandle);
  1180.     HLock(theHandle);
  1181.     return(hstate);
  1182. }
  1183.  
  1184.  
  1185.  
  1186. /*****************************************************************************/
  1187.  
  1188.  
  1189.  
  1190. /* InitGraf is always implemented (trap $A86E).  If the trap table is big
  1191. ** enough, trap $AA6E will always point to either Unimplemented or some other
  1192. ** trap, but will never be the same as InitGraf.  Thus, you can check the size
  1193. ** of the trap table by asking if the address of trap $A86E is the same as
  1194. ** $AA6E. */
  1195.  
  1196. #pragma segment UtilInit
  1197. short    NumToolboxTraps(void)
  1198. {
  1199.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1200.         return (0x200);
  1201.     else
  1202.         return (0x400);
  1203. }
  1204.  
  1205.  
  1206.  
  1207. /*****************************************************************************/
  1208.  
  1209.  
  1210.  
  1211. /* Given any control handle, this will draw an outline around it.  This is used
  1212. ** for the default button of a window.  The extra nice feature here is that
  1213. ** I’ll erase the outline for buttons that are inactive.  Seems like there
  1214. ** should be a Toolbox call for getting a control’s hilite state.  Since there
  1215. ** isn’t, I have to look into the control record myself.  This should be called
  1216. ** for update and activate events.
  1217. **
  1218. ** The method for determining the oval diameters for the roundrect is a little
  1219. ** different than that recommended by Inside Mac. IM I-407 suggests that you
  1220. ** use a hardcoded (16,16) for the diameters.  However, this only looks good
  1221. ** for small roundrects.  For larger ones, the outline doesn’t follow the inner
  1222. ** roundrect because the CDEF for simple buttons doesn’t use (16,16).  Instead,
  1223. ** it uses half the height of the button as the diameter.  By using this
  1224. ** formula, too, our outlines look better.
  1225. **
  1226. ** WARNING: This will set the current port to the control’s window. */
  1227.  
  1228. #pragma segment UtilMain
  1229. void    OutlineControl(ControlHandle button)
  1230. {
  1231.     Rect        theRect;
  1232.     PenState    curPen;
  1233.     short        buttonOval;
  1234.  
  1235.     if (button) {
  1236.         SetPort((*button)->contrlOwner);
  1237.         GetPenState(&curPen);
  1238.         PenNormal();
  1239.         theRect = (*button)->contrlRect;
  1240.         InsetRect(&theRect, kButtonFrameInset, kButtonFrameInset);
  1241.         buttonOval = (theRect.bottom - theRect.top) / 2 + 2;
  1242.  
  1243.         PenPat((*button)->contrlHilite == kCntlActivate ? QD(black) : QD(gray));
  1244.  
  1245.         PenSize(kButtonFrameSize, kButtonFrameSize);
  1246.         FrameRoundRect(&theRect, buttonOval, buttonOval);
  1247.         SetPenState(&curPen);
  1248.     }
  1249. }
  1250.  
  1251.  
  1252.  
  1253. /*****************************************************************************/
  1254.  
  1255.  
  1256.  
  1257. #pragma segment UtilMain
  1258. void    OutlineDialogItem(DialogPtr dlgPtr, short item)
  1259. {
  1260.     short iKind;
  1261.     Handle iHandle;
  1262.     Rect iRect;
  1263.  
  1264.     GetDItem (dlgPtr, item, &iKind, &iHandle, &iRect);
  1265.     OutlineControl((ControlHandle) iHandle);
  1266. }
  1267.  
  1268.  
  1269.  
  1270. /*****************************************************************************/
  1271.  
  1272.  
  1273.  
  1274. /* Given two rectangles, this function positions the second within the first
  1275. ** one so that it maintains the spacing specified by the horzRatio and
  1276. ** vertRatio parameters.  In other words, to center an inner rectangle
  1277. ** hoizontally, but have its center be 1/3 from the top of the outer rectangle,
  1278. ** call this function with horzRatio = FixRatio (1, 2), vertRatio =
  1279. ** FixRatio(1, 3).  We use Fixed rather than floating point to avoid
  1280. ** complications when mixing MC68881/non-MC68881 versions of Utilities. */
  1281.  
  1282. #pragma segment UtilMain
  1283. void    PositionRectInRect(Rect outerRect, Rect *innerRect, Fixed horzRatio, Fixed vertRatio)
  1284. {
  1285.     short        outerRectHeight;
  1286.     short        outerRectWidth;
  1287.     short        innerRectHeight;
  1288.     short        innerRectWidth;
  1289.     short        yLocation;
  1290.     short        xLocation;
  1291.  
  1292.     outerRectHeight = outerRect.bottom - outerRect.top;
  1293.     outerRectWidth = outerRect.right - outerRect.left;
  1294.  
  1295.     innerRectHeight = innerRect->bottom - innerRect->top;
  1296.     innerRectWidth = innerRect->right - innerRect->left;
  1297.         yLocation = Fix2Long(FixMul(Long2Fix(outerRectHeight - innerRectHeight), vertRatio))
  1298.             + outerRect.top;
  1299.         xLocation = Fix2Long(FixMul(Long2Fix(outerRectWidth - innerRectWidth), horzRatio))
  1300.             + outerRect.left;
  1301.  
  1302.     innerRect->top = yLocation;
  1303.     innerRect->left = xLocation;
  1304.     innerRect->bottom = yLocation + innerRectHeight;
  1305.     innerRect->right = xLocation + innerRectWidth;
  1306. }
  1307.  
  1308.  
  1309.  
  1310. /*****************************************************************************/
  1311.  
  1312.  
  1313.  
  1314. /* Concatenate a Pascal string onto another. */
  1315.  
  1316. #pragma segment UtilMain
  1317. void    PStrConcat(Str255 targetStr, Str255 appendStr)
  1318. {
  1319.     long appendLen;
  1320.  
  1321.     /* Figure out number of bytes to copy, up to 255 */
  1322.     if ((Length (targetStr) + Length (appendStr)) > 255)
  1323.         appendLen = 255 - Length (targetStr);
  1324.     else
  1325.         appendLen = Length (appendStr);
  1326.  
  1327.     if (appendLen > 0) {
  1328.         BlockMove (appendStr + 1, targetStr + Length (targetStr) + 1, appendLen);
  1329.         targetStr [0] += appendLen;
  1330.     }
  1331. }
  1332.  
  1333.  
  1334.  
  1335. /*****************************************************************************/
  1336.  
  1337.  
  1338.  
  1339. #pragma segment UtilInit
  1340. void    PullApplicationToFront(void)
  1341. {
  1342. #define kBroughtToFront 3
  1343.  
  1344.     EventRecord event;
  1345.     short        count;
  1346.  
  1347.     for (count = 1; count <= kBroughtToFront; count++)
  1348.         EventAvail(everyEvent, &event);
  1349. }
  1350.  
  1351.  
  1352.  
  1353. /*****************************************************************************/
  1354.  
  1355.  
  1356.  
  1357. /* Given the button control handle, this will cause the button to look as if it
  1358. ** has been clicked in.  This is nice to do for the user if they type return or
  1359. ** enter to select the default item. */
  1360.  
  1361. #pragma segment UtilMain
  1362. void    SelectButton(ControlHandle button)
  1363. {
  1364.     long            finalTicks;
  1365.     
  1366.     HiliteControl(button, kSelect);
  1367.     Delay(kDelayTime, &finalTicks);
  1368.     HiliteControl(button, kDeselect);
  1369. }
  1370.  
  1371.  
  1372.  
  1373. /*****************************************************************************/
  1374.  
  1375.  
  1376.  
  1377. /* Handy function for setting the value of a radio button.  Given a dialog
  1378. ** pointer, and item number, and a state, this function will take care of the
  1379. ** rest. */
  1380.  
  1381. #pragma segment UtilMain
  1382. void    SetCheckOrRadioButton(DialogPtr dlgPtr, short itemNo, short state)
  1383. {
  1384.     short    iKind;
  1385.     Handle    iHandle;
  1386.     Rect    iRect;
  1387.  
  1388.     GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  1389.     SetCtlValue((ControlHandle) iHandle, state);
  1390. }
  1391.  
  1392.  
  1393.  
  1394. /*****************************************************************************/
  1395.  
  1396.  
  1397.  
  1398. /* This algorithm for staggering windows does quite a good job.  It also is
  1399. ** quite gnarly.  Here's the deal:
  1400. ** There are pre-designated positions that we will try when positioning a
  1401. ** window.  These slots will be tried from the upper-left corner towards the
  1402. ** lower-right corner.  If there are other windows in that slot, then we will
  1403. ** consider that slot taken, and proceed to the next slot.  A slot is
  1404. ** determined to be taken by checking a point with a slop area.  This slop
  1405. ** area is diamond-shaped, not simply rectangular.  If there is no other
  1406. ** visible window with an upper-left corner within the slopt diamond, then
  1407. ** we are allowed to position our window there.
  1408. ** The above rule holds true unless this forces the window to be partly
  1409. ** off the screen.  If the window ends up partly off the screen, then we try
  1410. ** a new diagonal just below the first diagonal we tried.  We keep trying
  1411. ** lower and lower diagonals until we find a spot for the window, or the
  1412. ** diagonal doesn't fit on the screen at all.  If the diagonal doesn't fit,
  1413. ** then we try diagonals to the right of the first diagonal.  If even this
  1414. ** doesn't work, then we give up and put the window in the original spot
  1415. ** we tried. */
  1416.  
  1417. #pragma segment UtilMain
  1418. Rect    StaggerWindow(WindowPtr window, WindowPtr relatedWindow)
  1419. {
  1420.     WindowPtr    whichDevice, staggerFromWindow;
  1421.     Rect        deviceRect, oldWindowRect, newWindowRect, slot1;
  1422.     Rect        testRect, contentRect, staggerFromRect;
  1423.     Point        delta, absdelta;
  1424.     Boolean        contained, vertTry;
  1425.     short        diamondSize, diagNum, tryNum;
  1426.  
  1427.     if (!(whichDevice = relatedWindow)) whichDevice = window;
  1428.         /* If we have a window to stagger from, use the device for that window,
  1429.         ** else use the device for the window that is getting staggered. */
  1430.  
  1431.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  1432.         /* We now have the rect of the device we want to stagger within. */
  1433.  
  1434.     oldWindowRect = GetWindowStructureRect(window);
  1435.     newWindowRect.top    = deviceRect.top  + kStartPtV;
  1436.     newWindowRect.left   = deviceRect.left + kStartPtH;
  1437.     newWindowRect.bottom = newWindowRect.top  + oldWindowRect.bottom - oldWindowRect.top;
  1438.     newWindowRect.right  = newWindowRect.left + oldWindowRect.right  - oldWindowRect.left;
  1439.         /* We now have a new rect for the first window position slot. */
  1440.  
  1441.     slot1 = newWindowRect;
  1442.         /* We keep this slot in case we find no acceptable slots.  If we
  1443.         ** don't find an acceptable one, we will use this one anyway. */
  1444.  
  1445.     diamondSize = (kStaggerH < kStaggerV) ? kStaggerH : kStaggerV;
  1446.     for (diagNum = 0, vertTry = true;;) {
  1447.         for (tryNum = 0;; ++tryNum) {
  1448.  
  1449.             SectRect(&newWindowRect, &deviceRect, &testRect);
  1450.             if (!(contained = EqualRect(&newWindowRect, &testRect))) break;
  1451.                 /* Break if the slot we are testing went off the device. */
  1452.  
  1453.             for (staggerFromWindow = FrontWindow();
  1454.                  staggerFromWindow;
  1455.                  staggerFromWindow =
  1456.                     (WindowPtr)((WindowPeek)staggerFromWindow)->nextWindow
  1457.             ) {
  1458.                 if (!((WindowPeek)staggerFromWindow)->visible) continue;
  1459.                     /* This window is invisible.  Staggering from an invisible
  1460.                     ** window is going to confuse the user, so don't do it. */
  1461.  
  1462.                 testRect = GetWindowDeviceRectNMB(staggerFromWindow);
  1463.                 if (!EqualRect(&testRect, &deviceRect)) continue;
  1464.                     /* This window doesn't belong to the device we are trying to
  1465.                     ** stagger on, so skip it and go to the next window. */
  1466.  
  1467.                 staggerFromRect = GetWindowStructureRect(staggerFromWindow);
  1468.                 delta.v = staggerFromRect.top  - newWindowRect.top;
  1469.                 delta.h = staggerFromRect.left - newWindowRect.left;
  1470.                 if ((absdelta.v = delta.v) < 0) absdelta.v = -delta.v;
  1471.                 if ((absdelta.h = delta.h) < 0) absdelta.h = -delta.h;
  1472.                 if ((absdelta.h + absdelta.v) < diamondSize) {
  1473.                     if ((delta.h + delta.v) > 0)
  1474.                         OffsetRect(&newWindowRect, delta.h, delta.v);
  1475.                             /* If the window that took our slot is closer to
  1476.                             ** the lower-right corner than we are, then use
  1477.                             ** this window's location as the basis for the
  1478.                             ** slots from now on.  This will align new windows
  1479.                             ** with previous windows that are not gridded to
  1480.                             ** the default slot positions.  The check for > 0
  1481.                             ** is necessary to prevent bouncing between two
  1482.                             ** existing windows.  This check guarantees that
  1483.                             ** we are progressing with the evaluation. */
  1484.                     break;
  1485.                         /* Break because this slot is already used. */    
  1486.                 }
  1487.             }
  1488.  
  1489.             if (!staggerFromWindow) break;
  1490.                 /* If the window pointer is nil, then we tried all the windows
  1491.                 ** and none of them occupied this slot.  This means that the
  1492.                 ** slot is available for the new window. */
  1493.  
  1494.                 OffsetRect(&newWindowRect, kStaggerH, kStaggerV);
  1495.                 /* Since this slot was taken, try the next slot and go through
  1496.                 ** the window list again. */
  1497.         }
  1498.  
  1499.         if (contained) break;
  1500.         newWindowRect = slot1;
  1501.         if (!tryNum) {
  1502.             if (!vertTry) break;        /* Nothing works.  No spots at all. */
  1503.             vertTry = false;            /* Try across for the next pass. */
  1504.             diagNum = 0;
  1505.         }
  1506.         ++diagNum;
  1507.         if (vertTry) OffsetRect(&newWindowRect, 0, diagNum * kStaggerV);
  1508.         else         OffsetRect(&newWindowRect, diagNum * kStaggerH, 0);
  1509.     }
  1510.  
  1511.     contentRect = GetWindowContentRect(window);
  1512.         /* Get where the window is now. */
  1513.  
  1514.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  1515.                             newWindowRect.top  - oldWindowRect.top);
  1516.         /* Calculate the new content rect. */
  1517.  
  1518.     MoveWindow(window, contentRect.left, contentRect.top, false);
  1519.         /* Move the window to the new location. */
  1520.  
  1521.     return(contentRect);
  1522. }
  1523.  
  1524.  
  1525.  
  1526. /*****************************************************************************/
  1527.  
  1528.  
  1529.  
  1530. #pragma segment UtilMain
  1531. void    StandardAbout(short appNameStringID)
  1532. {
  1533.     StringHandle    apNameHndl;
  1534.     VersRecHndl        curVersion;
  1535.     Str255            apName;
  1536.     Str255            verNum = "\p????";
  1537.     Ptr                verNumLocation;
  1538.     OSErr            err;
  1539.  
  1540.     if (!gUtilitiesInited)                /* Make sure we were initialized */
  1541.         InitUtilities();
  1542.         
  1543.     apNameHndl = (StringHandle)nil;
  1544.     if (appNameStringID != kUseRealAppName) {
  1545.         if (appNameStringID != kUseCreatorString)
  1546.             apNameHndl = GetString(appNameStringID);
  1547.         if (!apNameHndl)
  1548.             apNameHndl = (StringHandle) GetAppResource(gSignature, 0, &err);
  1549.     }
  1550.  
  1551.     if ((!apNameHndl) || (appNameStringID == kUseRealAppName))
  1552.         PStrCopy(apName, gAppName);
  1553.     else
  1554.         PStrCopy(apName, *apNameHndl);
  1555.  
  1556.     curVersion = (VersRecHndl) GetAppResource('vers', 1, &err);
  1557.     if (curVersion) {
  1558.         verNumLocation = (Ptr) ((long)(*curVersion)->shortVersion
  1559.                         + (long)*(*curVersion)->shortVersion + 1);
  1560.         PStrCopy(verNum, verNumLocation);
  1561.     }
  1562.  
  1563.     ParamText(apName, verNum, '', '');
  1564.  
  1565.     CenteredAlert(rStdAboutAlert, nil);
  1566. }
  1567.  
  1568.  
  1569.  
  1570. /*****************************************************************************/
  1571.  
  1572.  
  1573.  
  1574. #pragma segment UtilInit
  1575. void    StandardInitialization(short callsToMoreMasters)
  1576. {
  1577.     InitToolBox();
  1578.  
  1579.     while (callsToMoreMasters--)
  1580.         MoreMasters();
  1581.     
  1582.     PullApplicationToFront();
  1583.     
  1584.     InitUtilities();
  1585. }
  1586.  
  1587.  
  1588.  
  1589. /*****************************************************************************/
  1590.  
  1591.  
  1592.  
  1593. #pragma segment UtilInit
  1594. void    StandardMenuSetup(short MBARID, short AppleMenuID)
  1595. {
  1596.     Handle menuBar = GetNewMBar(MBARID);            /* read menus into menu bar */
  1597.     if (!menuBar) 
  1598.         DeathAlert(rUtilStrings, eNoMenuBar);
  1599.     SetMenuBar(menuBar);                            /* install menus */
  1600.     DisposHandle(menuBar);
  1601.     AddResMenu(GetMHandle(AppleMenuID), 'DRVR');    /* add DA names to Apple menu */
  1602.     DrawMenuBar();
  1603. }
  1604.  
  1605.  
  1606.  
  1607. /*****************************************************************************/
  1608.  
  1609.  
  1610.  
  1611. #pragma segment UtilMain
  1612. void    ToggleCheck(DialogPtr dlgPtr, short chkItem)
  1613. {
  1614.     short iKind;
  1615.     Handle iHandle;
  1616.     Rect iRect;
  1617.  
  1618.     GetDItem (dlgPtr, chkItem, &iKind, &iHandle, &iRect);
  1619.     SetCtlValue((ControlHandle) iHandle, !GetCtlValue((ControlHandle)iHandle));
  1620. }
  1621.  
  1622.  
  1623.  
  1624. /*****************************************************************************/
  1625.  
  1626.  
  1627.  
  1628. /* Check to see if a given trap is implemented.  This is only used by the
  1629. ** Initialize function in this program, so we put it in the
  1630. ** Initialize segment. */ 
  1631.  
  1632. #pragma segment UtilInit
  1633. Boolean TrapExists(short theTrap)
  1634. {
  1635.     TrapType    theTrapType;
  1636.  
  1637.     theTrapType = GetTrapType(theTrap);
  1638.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  1639.         theTrap = _Unimplemented;
  1640.  
  1641.     return (NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap,
  1642.                   theTrapType));
  1643. }
  1644.  
  1645.  
  1646.  
  1647. /*****************************************************************************/
  1648.  
  1649.  
  1650.  
  1651. /* Zoom the window to the size appropriate for the device that contains the
  1652. ** most of the window.  An additional feature is that you can state the
  1653. ** maximum that a window should be zoomed, either horizontally or vertically.
  1654. ** If you pass in a maximum of 0 for the zoom for either direction, then that
  1655. ** direction will be zoomed to fit the device. */
  1656.  
  1657. #pragma segment UtilMain
  1658. void    ZoomToWindowDevice(WindowPtr window, short maxWidth, short maxHeight,
  1659.                            short zoomDir, Boolean front)
  1660. {
  1661.      GrafPtr        oldPort;
  1662.     Rect        contentRect, structureRect, deviceRect, newRect;
  1663.     short        width, height, dx, dy;
  1664.  
  1665.     GetPort(&oldPort);
  1666.     SetPort(window);
  1667.     EraseRect(&window->portRect);         /* Recommended for cosmetic reasons. */
  1668.  
  1669.     /* If there is the possibility of multiple gDevices, then we must check them to
  1670.     ** make sure we are zooming onto the right display device when zooming out. */
  1671.  
  1672.     if ((zoomDir == inZoomOut) && (gQDVersion > kQDOriginal)) {
  1673.  
  1674.         contentRect      = GetWindowContentRect(window);
  1675.         structureRect = GetWindowStructureRect(window);
  1676.         deviceRect      = GetWindowDeviceRectNMB(window);
  1677.  
  1678.         deviceRect.left   += (contentRect.left - structureRect.left + 2);
  1679.         deviceRect.top    += (contentRect.top - structureRect.top + 2);
  1680.         deviceRect.right  -= (structureRect.right - contentRect.right + 2);
  1681.         deviceRect.bottom -= (structureRect.bottom - contentRect.bottom + 2);
  1682.         newRect = deviceRect;
  1683.  
  1684.         if (maxWidth)
  1685.             if ((width = deviceRect.right - deviceRect.left) > maxWidth)
  1686.                 newRect.right = (newRect.left = contentRect.left) + maxWidth;
  1687.         if (maxHeight)
  1688.             if ((height = deviceRect.bottom - deviceRect.top) > maxHeight)
  1689.                 newRect.bottom = (newRect.top = contentRect.top) + maxHeight;
  1690.         if ((dx = deviceRect.left - newRect.left) < 0)
  1691.             if ((dx = deviceRect.right - newRect.right) > 0)
  1692.                 dx = 0;
  1693.         if ((dy = deviceRect.top - newRect.top) < 0)
  1694.             if ((dy = deviceRect.bottom - newRect.bottom) > 0)
  1695.                 dy = 0;
  1696.         OffsetRect(&newRect, dx, dy);
  1697.  
  1698.         (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->stdState = newRect;
  1699.             /* Set up the WStateData record for this window. */
  1700.     }
  1701.  
  1702.     ZoomWindow(window, zoomDir, front);
  1703.     SetPort(oldPort);
  1704. }
  1705.  
  1706.  
  1707.  
  1708.